File: CachingBase`1.cs
Web Access
Project: ..\..\..\src\Microsoft.CodeAnalysis.NetAnalyzers\tests\Test.Utilities\Test.Utilities.csproj (Test.Utilities)
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the MIT license.  See License.txt in the project root for license information.
 
using System.Diagnostics;
 
namespace Analyzer.Utilities
{
    internal abstract class CachingBase<TEntry>
    {
        private readonly int _alignedSize;
        private TEntry[]? _entries;
 
        // cache size is always ^2. 
        // items are placed at [hash ^ mask]
        // new item will displace previous one at the same location.
        protected readonly int mask;
 
        // See docs for createBackingArray on the constructor for why using the non-threadsafe ??= is ok here.
        protected TEntry[] Entries => _entries ??= new TEntry[_alignedSize];
 
        /// <param name="createBackingArray">Whether or not the backing array should be created immediately, or should
        /// be deferred until the first time that <see cref="Entries"/> is used.  Note: if <paramref
        /// name="createBackingArray"/> is <see langword="false"/> then the array will be created in a non-threadsafe
        /// fashion (effectively different threads might observe a small window of time when different arrays could be
        /// returned.  Derived types should only pass <see langword="false"/> here if that behavior is acceptable for
        /// their use case.</param>
        internal CachingBase(int size, bool createBackingArray = true)
        {
            _alignedSize = AlignSize(size);
            this.mask = _alignedSize - 1;
            _entries = createBackingArray ? new TEntry[_alignedSize] : null;
        }
 
        private static int AlignSize(int size)
        {
            Debug.Assert(size > 0);
 
            size--;
            size |= size >> 1;
            size |= size >> 2;
            size |= size >> 4;
            size |= size >> 8;
            size |= size >> 16;
            return size + 1;
        }
    }
}